/*
 * Copyright (c) Jack魏 2023 - 2023, All Rights Reserved.
 */

package cn.jack1996.yiyi.auth;

import java.io.IOException;

import cn.jack1996.yiyi.bean.SysUser;
import cn.jack1996.yiyi.service.sys.SysUserService;
import cn.jack1996.yiyi.util.JwtUtil;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import cn.hutool.core.text.CharSequenceUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * Security权限过滤器
 *
 * @author Jack魏
 * @since 2023/2/15 0:14
 */
@Component
public class AuthenticationFilter extends OncePerRequestFilter {
    /**
     * 前端请求头字段
     */
    private static final String AUTHORIZATION = "Authorization";
    /**
     * 登录接口，需要放行
     */
    private static final String LOGIN_URL = "/yiyi/sys/login";

    @Resource
    private SysUserService sysUserService;

    /**
     * Security过滤器，每次请求都会经过这里
     *
     * @param request 前端请求
     * @param response 后端响应
     * @param filterChain 过滤链
     * @throws ServletException servlet异常
     * @throws IOException io异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        // 放行登录接口
        if (LOGIN_URL.equals(request.getRequestURI())) {
            filterChain.doFilter(request, response);
            return;
        }
        // 从请求头里获取token值
        final String token = request.getHeader(AUTHORIZATION);
        String tip = JwtUtil.verify(token);
        if (CharSequenceUtil.isNotBlank(tip)) {
            throw new BadCredentialsException(tip);
        }
        String userId = (String) JwtUtil.getClaim(token, "userId");
        // 从数据库查询用户信息
        SysUser user = sysUserService.getById(userId);
        CustomUserDetails userDetails = new CustomUserDetails(user);
        // 将用户详情数据存储到全局上下文里，后面可以直接拿出来用户信息
        SecurityContextHolder.getContext()
            .setAuthentication(UsernamePasswordAuthenticationToken.authenticated(userDetails, null, null));
        filterChain.doFilter(request, response);
    }
}
